﻿#include "appconfig.h"
#include "appcontroller.h"
#include <QDebug>

AppController* g_Controller = nullptr;

AppController::AppController()
    : m_SenderAndReciver(nullptr)
{
    Init();
}

AppController::~AppController()
{

}

AppController *AppController::Instance()
{
    if (g_Controller == nullptr)
        g_Controller = new AppController;

    return g_Controller;
}

void AppController::Destroy()
{
    if (g_Controller != nullptr)
        delete g_Controller;

    g_Controller = nullptr;
}

void AppController::Init()
{
    m_SenderAndReciver = new udpSenderAndReceiver(this);
    if (nullptr == m_SenderAndReciver)
    {
        //报错提示
        qDebug() << "Init error";
    }

}

int AppController::SendData(QByteArray &data)
{
    int ret = -1;
    if (nullptr == m_SenderAndReciver)
    {
        Init();

    }
    if(COMM_OK != (ret= StartController())){

        //显示错误信息退出
        qDebug() << "ret = " << ret << __FUNCTION__ <<__LINE__;
        return ret;
    }
    ret = m_SenderAndReciver->SendData(data);
    qDebug() << "SendData ret = " << ret << __FUNCTION__ <<__LINE__;
    return ret;
}

void AppController::ResetController()
{
    qDebug() << "enter " << __FUNCTION__ <<__LINE__;
    //先停止，再delete，最后再重新初始化
    StopController();
    delete m_SenderAndReciver;
    Init();
    qDebug() << "leave " << __FUNCTION__ <<__LINE__;
}

int AppController::ErrorCode()
{
    if (nullptr == m_SenderAndReciver)
        return -9999;

    return m_SenderAndReciver->ErrorCode();
}

int AppController::StartController()
{
    int ret = -1;
    qDebug()<<"m_SenderAndReciver=" <<m_SenderAndReciver<< __FUNCTION__<<__LINE__;

    if (nullptr != m_SenderAndReciver){
         ret = m_SenderAndReciver->StartBroadCastSocket();
    }
    return ret;
}

void AppController::StopController()
{
    if (nullptr != m_SenderAndReciver)
        m_SenderAndReciver->AbortBroadCastSocket();
}

AppController::RunStatus AppController::Status()
{
    if (m_SenderAndReciver)
    {
        return m_SenderAndReciver && m_SenderAndReciver->isRunning() ? Starting : Abort;
    }

    return Abort;
}

udpSenderAndReceiver::udpSenderAndReceiver(AppController* controller)
    : m_Controller(controller)
     , m_UdpSocket(nullptr)
{
    //InitBroadCastSocket();
}

udpSenderAndReceiver::~udpSenderAndReceiver()
{
    if (nullptr != m_UdpSocket)
    {
        disconnect(m_UdpSocket, SIGNAL(readReady()), this, SLOT(OnReciveCastData()));
        m_UdpSocket->abort();//(QHostAddress::Any, config->BroadCastPort()); // 绑定到本地的端口号，需与发送端相同的端口号
        delete m_UdpSocket;
        m_UdpSocket = nullptr;
    }
}

int udpSenderAndReceiver::StartBroadCastSocket()
{
    bool bret = true;
    AppConfig* config = AppConfig::Instance();
    if (nullptr == config)
        return ERR_NO_MEMORY;
    qDebug() << "enter " << __FUNCTION__<< m_UdpSocket;
    if (nullptr == m_UdpSocket)
    {
        m_UdpSocket = new QUdpSocket(this);
        if(m_UdpSocket == nullptr){
            qDebug() << "create socket failed." << "udpSocket=%d" << m_UdpSocket;
            return ERR_CREATE_SOCKET;
        }
        qDebug() << "create socket success.";
        qDebug() << "config->CastType()=" << config->CastType();

        if(config->CastType() == MutiCast_type){
            /*对组播进行设置（可以忽略）*/
            //组播的数据的生存期，数据报没跨1个路由就会减1.表示多播数据报只能在同一路由下的局域网内传播
            m_UdpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);
            //1是允许loopback模式（自发自收）,0是阻止。
            m_UdpSocket->setSocketOption(QAbstractSocket::MulticastLoopbackOption, true);

            QHostAddress loacalAddress(config->LocalIP());
            //bret = m_UdpSocket->bind(loacalAddress, QUdpSocket::ShareAddress | QUdpSocket::ReuseAddressHint);
            bret = m_UdpSocket->bind(loacalAddress, config->MutiCastPort()); // QHostAddress::AnyIPv4绑定到本地的端口号，需与发送端相同的端口号
            if(bret == false){
               qDebug() << "bind socket failed."<<__FUNCTION__<<__LINE__<<"errno="<<errno;
                return ERR_BIND;
           }
            //m_UdpSocket->setMulticastInterface(currentInterface);
            qDebug() << "bind socket success."<<__FUNCTION__<<__LINE__<< config->MutiCastIP();
           QHostAddress groupAddress(config->MutiCastIP()); // 设置广播组地址
            bret = m_UdpSocket->joinMulticastGroup(groupAddress); // 加入广播组
           if(bret!= true){
                qDebug() << "joinMulticastGroup failed. errorcode:" ;
                return ERR_JOIN_MUTICAST_GROUP;
            }
           qDebug() << "joinMulticastGroup."<<__FUNCTION__<<__LINE__<< bret;
        }else if(config->CastType() == BroadCast_type){
            bret = m_UdpSocket->bind(QHostAddress::Any, config->BroadCastPort()); // 绑定到本地的端口号，需与发送端相同的端口号

            qDebug() << "bind socket "<<bret<<__FUNCTION__<<__LINE__ ;
        }else if(config->CastType() == UniCast_type){
#if _UNICAST_SERVER
            bret = m_UdpSocket->bind(QHostAddress::Any, config->TargetPort_UniCast());
            qDebug() << "bind socket " <<bret<<__FUNCTION__ <<__LINE__;
#else
            bret = m_UdpSocket->bind(QHostAddress::Any, config->LocalPort_UniCast());
            qDebug() << "bind socket " <<bret<<__FUNCTION__ <<__LINE__;
#endif

        }
        connect(m_UdpSocket, SIGNAL(readyRead()), this, SLOT(OnReceiveCastData()));
    }
    qDebug() << "leave" << __FUNCTION__ <<__LINE__<<bret;
    return (bret == true)? COMM_OK:ERR_BIND;
}



void udpSenderAndReceiver::AbortBroadCastSocket()
{
    if (nullptr != m_UdpSocket)
    {
        disconnect(m_UdpSocket, SIGNAL(readReady()), this, SLOT(OnReciveData()));
        m_UdpSocket->abort();//(QHostAddress::Any, config->BroadCastPort()); // 绑定到本地的端口号，需与发送端相同的端口号
        delete m_UdpSocket;
        m_UdpSocket = nullptr;
    }
}

void udpSenderAndReceiver::OnReceiveCastData()
{
     qDebug() << "enter " << __FUNCTION__<<m_UdpSocket->hasPendingDatagrams();
    if (m_UdpSocket->hasPendingDatagrams())
    {
        QHostAddress sender;
        quint16 senderPort;
        QByteArray datagram;
        datagram.resize(m_UdpSocket->pendingDatagramSize());
        if(AppConfig::Instance()->CastType() == UniCast_type){

        }
        m_UdpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
        qDebug() << "recvMsg=" << QString::fromLocal8Bit(datagram) << __FUNCTION__<<sender<<senderPort;
        // 处理接收到的数据
       // processData(datagram, sender, senderPort);
        AppController* m_Controller = AppController::Instance();
        if(m_Controller == nullptr){
            return;
        }
        emit m_Controller->ReceiveData(datagram);
    }
     qDebug() << "leave " << __FUNCTION__;
}


void udpSenderAndReceiver::run()
{
//    while(!m_bQuit)
//    {
//        QString data = m_UdpSocket->readDatagram();
//        //如果读到数据发送信号出去
//        emit RecievData(data);
//    }
}

int udpSenderAndReceiver::SendData(QByteArray &data)
{
    qint64 ret = -1;
    qDebug() << "enter "<< __FUNCTION__ <<__LINE__ << m_UdpSocket->isValid();
    if (m_UdpSocket->isValid())
    {
        AppConfig* config = AppConfig::Instance();
        if (nullptr == config){
            return ERR_NO_MEMORY;
        }
        qDebug() << "config->CastType()=" << config->CastType();
        if(config->CastType() == BroadCast_type){
            QHostAddress broadcastAddress(config->BroadCastIP());
            ret = m_UdpSocket->writeDatagram(data.data(), data.size(), broadcastAddress, config->BroadCastPort());
        }else if(config->CastType() == MutiCast_type){
            QHostAddress muticastAddress(config->MutiCastIP());
            ret = m_UdpSocket->writeDatagram(data.data(), data.size(), muticastAddress, config->MutiCastPort());
        }else if(config->CastType() == UniCast_type){
            QHostAddress unicastTargetIP(config->TargetIP_UniCast());
            ret = m_UdpSocket->writeDatagram(data.data(), data.size(),unicastTargetIP, config->TargetPort_UniCast());
            qDebug()<<"ret=" << ret <<__func__ <<__LINE__;

        }
        if(ret == -1 || ret != data.size()){
            qDebug() << "send data error.";
            return ERR_SEND;
        }
    }
    else
    {
        //报错异常
        qDebug() << "the socket is invalid or not ready for use";
        return ERR_CONNECT;
    }
    return COMM_OK;
}

int udpSenderAndReceiver::ErrorCode()
{
    return 0;
}




